package com.xike.micromemberserver.controller;

import com.alibaba.fastjson.JSONObject;
import com.xike.entiy.ResultBean;
import com.xike.micromemberserver.entity.MemberInfoEntity;
import com.xike.micromemberserver.entity.jwt.AuthResult;
import com.xike.micromemberserver.service.LoginService;
import com.xike.micromemberserver.uitl.JWTUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Auther: wuson  <br/>
 * Date: 2021/3/10:15:49  <br/>
 * Description:
 */
@Api("用户登录注册")
@Slf4j
@RequestMapping("/member/login")
@RestController
public class LogInController implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {
    @Autowired(required = false)
    private LoginService loginService;
    @Autowired(required = false)
   private RabbitTemplate rabbitTemplate;
    @ApiOperation("用户登录")
    @PostMapping(value = "/in",produces = MediaType.APPLICATION_JSON_VALUE)
    public String addOne(String account, String password){
        MemberInfoEntity memberInfoEntity = loginService.selectByAccount(account);
        String token = "";
        if(memberInfoEntity !=null&& memberInfoEntity.getAccount().equals(account)){
            if(memberInfoEntity.getPassword().equals(password)){
                //认证通过，产生JWT令牌
                Map<String, Object> claims = new HashMap<>();
                claims.put("memberAccount", memberInfoEntity.getAccount());
                claims.put("userName", memberInfoEntity.getUser_name());
                token = JWTUtil.createToken(claims);
                AuthResult authResult = AuthResult.builder().token(token).build();
                return JSONObject.toJSONString(ResultBean.builder().code(200).msg("登录成功").data(token).build());
            }
            return JSONObject.toJSONString(ResultBean.builder().code(200).msg("密码错误").build());
        }
        return JSONObject.toJSONString(ResultBean.builder().code(200).msg("无效账号").build());
    }
    @ApiOperation("用户注册")
    @PostMapping(value = "/register",produces = MediaType.APPLICATION_JSON_VALUE)
    public String register(MemberInfoEntity memberInfoEntity){
        //先向数据库中，添加数据
        log.info("接收到的注册信息：{}",memberInfoEntity);
        int state = loginService.register(memberInfoEntity);
        //向RabbitMQ中生产数据
        Map<String,Object> data = new HashMap<>();
        data.put("msg",memberInfoEntity.getUser_name() + "注册成功");
        data.put("email",memberInfoEntity.getEmail());
        data.put("id", UUID.randomUUID().toString());//幂等性ID
        //交换机的名称，路由键，具体的数据
        rabbitTemplate.convertAndSend("email_fanoutExchange",null,data);
        return JSONObject.toJSONString(ResultBean.builder().code(200).msg("注册成功").build());
    }

    @RequestMapping(value = "/send")
    public String sendMsg(String exchage,String routingKey,String msg){
        //针对当前消息开启确认回调
        rabbitTemplate.setConfirmCallback(this);
        //针对当前消息开启不可达回调
        rabbitTemplate.setReturnCallback(this);
        Map<String,Object> data = new HashMap<>();
        data.put("msg",msg);//传递的消息
        data.put("id",UUID.randomUUID().toString());
        //发送消息
        //设定关联数据ID
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(exchage,routingKey,data,correlationData);
        return JSONObject.toJSONString(ResultBean.builder().code(200).msg("发送成功").build());
    }

    /**
     * 异步确认
     * @param correlationData 关联数据
     * @param ack 确认情况
     * @param cause 错误原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        log.info("消息关联数据的ID--{}" , correlationData.getId());
        if(ack){
            log.info("消息关联数据的ID--{}，确认发送成功！" , correlationData.getId());
        }else{
            log.info("消息关联数据的ID" + correlationData.getId() + "发送失败，原因是：{}",cause);
        }
    }

    /**
     * 处理消息不可达
     * @param message
     * @param replyCode
     * @param replyText
     * @param exchange
     * @param routingKey
     */
    @Override
    public void returnedMessage(Message message,int replyCode, String replyText, String exchange, String routingKey) {
        try {
            log.info("消息不可达，消息是：{}，状态码是: {},返回内容：{}，交换机是：{}，路由Key是：{}",
                    new String(message.getBody(),"UTF-8"),
                    replyCode,replyText,exchange,routingKey);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}
